package com.innovation.util.config;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

public class JSGenerator {
	public static void main(String[] args) throws ClassNotFoundException, IOException {
		String hFolder = "D:\\project\\tanchishe\\Snake-Client\\Snake\\src\\config\\";
//		String hFolder = "D:\\dev\\work\\sanguo\\SanguoShare\\client\\libProtos\\config\\";
		generateJS(hFolder);
	}

	private static void generateJS(String hFolder) throws ClassNotFoundException, IOException {
		/*List<String> classes = PackageUtil.getClassName(ConfigPlayerLevel.class.getPackage().getName(), false);
//		PrintWriter out = new PrintWriter(cppFolder + "register.cpp");
//		StringBuffer reg = new StringBuffer("void initConfigClasses()\n{\n");
		try {
//			out.println("#include \"serialize.h\"");
//			out.println("#include \"register.h\"");
			for (String cName : classes) {
				// 过滤掉Example类型
				if (!cName.endsWith("Example")) {
					Class<?> clazz = Class.forName(cName);
					if (clazz.getSimpleName().startsWith("Config")) {
						if(clazz.getSimpleName().equals("ConfigMissionReward")){
							continue;
						}
						if(clazz.getSimpleName().equals("ConfigRandomMission")){
							continue;
						}
						System.out.println(hFolder + clazz.getSimpleName() + ".js");
//						String fileName = clazz.getSimpleName() + ".h";
						genJS(clazz, hFolder + clazz.getSimpleName() + ".js");
//						out.append("#include \"").append(fileName).println("\"");
//						reg.append("\tXREGEST_CLASS(").append(clazz.getSimpleName()).append(");\n");
					}
				}
			}
//			reg.append("}\n");
//			out.append(reg);
//			out.flush();
		} finally {
//			out.close();
		}*/
	}

	/**
	 * 通过Class生成指定的头文件和CPP文件
	 * 
	 * @param type
	 * @param hFile
	 * @param cppFile
	 * @throws IOException
	 */
	public static void genJS(Class<?> type, String hFile) throws IOException {
		PrintWriter out = new PrintWriter(hFile);
		try {
			out.println("// generate by JSGenerate");
			out.println("// do not modify it");
			out.append("var ").append(type.getSimpleName()).println(" = function(){");
			List<Field> fields = SimpleObjectOutputStream.getFieldList(type);
			for (Field f : fields) {
				TypeInfo typeInfo = getTypeInfo(f.getType());
				if (typeInfo == null) {
//					throw new RuntimeException("field type is unknow:" + f);
					out.append("\tthis.").append(f.getName()).println(" = null;");
				}else
					out.append("\tthis.").append(f.getName()).append(" = ").append(typeInfo.defaultValue).println(";");
			}
			out.println("};");

			out.append(type.getSimpleName()).println(".prototype.read = function(dis){");
			for (Field f : fields) {
				TypeInfo typeInfo = getTypeInfo(f.getType());
				if (typeInfo == null) {
//					throw new RuntimeException("field type is unknow:" + f);
					out.append("\tthis.").append(f.getName()).println(" = dis.readObject();");
				}else
					out.append("\tthis.").append(f.getName()).append(" = dis.").append(typeInfo.functionName).println("();");
			}

			out.println("};");
			out.flush();
		} finally {
			out.close();
		}

	}

	static Map<Class<?>, TypeInfo> typeMap = new Hashtable<Class<?>, TypeInfo>();

	static void putType(TypeInfo info, Class<?>... classes) {
		for (Class<?> c : classes) {
			typeMap.put(c, info);
		}
	}

	static {
		putType(new TypeInfo("readInt", "0"), int.class, Integer.class, Date.class);
		putType(new TypeInfo("readFloat", "0"), float.class, Float.class);
		putType(new TypeInfo("readShort", "0"), short.class, Short.class);
		putType(new TypeInfo("readByte", "0"), byte.class, Byte.class);
		putType(new TypeInfo("readBoolean", "false"), boolean.class, Boolean.class);
		putType(new TypeInfo("readUtf", "\"\""), String.class);
		putType(new TypeInfo("readLong", "0"), long.class, Long.class);

	}

	private static TypeInfo getTypeInfo(Class<?> type) {
		return typeMap.get(type);
	}

	static class TypeInfo {
		String functionName;
		String defaultValue;

		protected TypeInfo(String functionName, String defaultValue) {
			super();
			this.functionName = functionName;
			this.defaultValue = defaultValue;
		}

	}

}
